package com.jj.core.utils;

public class Hex {
    public static Object lock = new Object();
    //public static String OFFSET = "\nOFST  00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F\n";
    public static void printhex(byte[] buf)
    {
        printhex(buf, buf.length);
    }

    public static String printhex2Buf(byte[] buf)
    {
        return printhex2Buf(buf, buf.length);
    }

    public static void printhex( byte[] buf, int size ) {
        int x, y;

        //System.out.println("offset 0  1  2  3  4  5  6  7   8  9  a  b  c  d  e  f");

        for( x=1; x<=size; x++ ) {

            if( x == 1 ) System.out.printf("%04x  ", x-1 ); /* Print an offset line header */

            System.out.printf( "%02x ", buf[x-1] ); /* print the hex value */

            if( x % 8 == 0 ) System.out.printf( " " ); /* padding space at 8 and 16 bytes */

            if( x % 16 == 0 ) {
				/* We're at the end of a line of hex, print the printables */
                System.out.printf( " " );
                for( y = x - 15; y <= x; y++ ) {
                    if( isprint( buf[y-1] ) ) System.out.printf( "%c", buf[y-1] ); /* if it's printable, print it */
                    else System.out.printf( "." ); /* otherwise substitute a period */
                    if( y % 8 == 0 ) System.out.printf( " " ); /* 8 byte padding space */
                }
                if( x < size ) System.out.printf( "\n%04x  ", x ); /* Print an offset line header */
            }
        }
        x--;

		/* If we didn't end on a 16 byte boundary, print some placeholder spaces before printing ascii */
        if( x % 16 != 0 ) {
            for( y = x+1; y <= x + (16-(x % 16)); y++ ) {
                System.out.printf( "   " ); /* hex value placeholder spaces */
                if( y % 8 == 0 ) System.out.printf( " " ); /* 8 and 16 byte padding spaces */
            };

			/* print the printables */
            System.out.printf( " " );
            for( y = (x+1) - (x % 16); y <= x; y++ ) {
                if( isprint( buf[y-1] ) ) System.out.printf( "%c", buf[y-1] ); /* if it's printable, print it */
                else System.out.printf( "." ); /* otherwise substitute a period */
                if( y % 8 == 0 ) System.out.printf( " " ); /* 8 and 16 byte padding space */
            }
        }

		/* Done! */
        System.out.printf( "\n" );
    }

    public static String printhex2Buf( byte[] buf, int size ) {
        int x, y;
        StringBuffer strBuf = new StringBuffer("");

        //System.out.println("offset 0  1  2  3  4  5  6  7   8  9  a  b  c  d  e  f");
        //strBuf.append("offset 0  1  2  3  4  5  6  7   8  9  a  b  c  d  e  f\n");
        for( x=1; x<=size; x++ ) {

            if( x == 1 ){
                //System.out.printf("%04x  ", x-1 ); /* Print an offset line header */
                strBuf.append(String.format("%04x  ", x-1 ));
            }

            //System.out.printf( "%02x ", buf[x-1] ); /* print the hex value */
            strBuf.append(String.format( "%02x ", buf[x-1] ));

            if( x % 8 == 0 ){
                //System.out.printf( " " ); /* padding space at 8 and 16 bytes */
                strBuf.append(String.format( " " ));
            }

            if( x % 16 == 0 ) {
				/* We're at the end of a line of hex, print the printables */
                //System.out.printf( " " );
                strBuf.append(String.format( " " ));
                for( y = x - 15; y <= x; y++ ) {
                    if( isprint( buf[y-1] ) ) {
                        //System.out.printf( "%c", buf[y-1] ); /* if it's printable, print it */
                        strBuf.append(String.format( "%c", buf[y-1] ));
                    }
                    else {
                        //System.out.printf( "." ); /* otherwise substitute a period */
                        strBuf.append(String.format( "." ));
                    }
                    if( y % 8 == 0 ){
                        //System.out.printf( " " ); /* 8 byte padding space */
                        strBuf.append(String.format( " " ));
                    }
                }
                if( x < size ) {
                    //System.out.printf( "\n%04x  ", x ); /* Print an offset line header */
                    strBuf.append(String.format( "\n%04x  ", x ));
                }
            }
        }
        x--;

		/* If we didn't end on a 16 byte boundary, print some placeholder spaces before printing ascii */
        if( x % 16 != 0 ) {
            for( y = x+1; y <= x + (16-(x % 16)); y++ ) {
                //System.out.printf( "   " ); /* hex value placeholder spaces */
                strBuf.append(String.format( "   "));
                if( y % 8 == 0 ){
                    //System.out.printf( " " ); /* 8 and 16 byte padding spaces */
                    strBuf.append(String.format( " "));
                }
            };

			/* print the printables */
            //System.out.printf( " " );
            strBuf.append(String.format( " "));
            for( y = (x+1) - (x % 16); y <= x; y++ ) {
                if( isprint( buf[y-1] ) ){
                    //System.out.printf( "%c", buf[y-1] ); /* if it's printable, print it */
                    strBuf.append(String.format( "%c", buf[y-1] ));
                }
                else{
                    //System.out.printf( "." ); /* otherwise substitute a period */
                    strBuf.append(String.format( "." ));
                }
                if( y % 8 == 0 ){
                    System.out.printf( " " ); /* 8 and 16 byte padding space */
                    strBuf.append(String.format( " " ));
                }
            }
        }

		/* Done! */
        //System.out.printf( "\n" );
        strBuf.append(String.format( "\n" ));
        //return (OFFSET + strBuf.toString());
        return strBuf.toString();
    }


    public static boolean isprint (int ch)
    {
        return (ch >= ' ' && ch <= '~');
    }

    public static void dumpBytes(byte[] bytes)
    {
        synchronized(lock)
        {
            printhex(bytes,bytes.length);
        }
    }

    public static void dumpTrace()
    {
        Throwable t = new Throwable();
        StackTraceElement stack[] = t.getStackTrace();
        int i = 1;
        String dumpMsg = null;
        while (i != (stack.length)) {
            dumpMsg = "[" + (stack.length - i) + "]" +stack[i].toString();
            System.out.println(dumpMsg);
            i++;
        }
        return;
    }

    public static void main(String[] args)
    {
        byte[] data = {0x01, 0x42, 0x43, (byte) 0x4F, 0x47};
        String msg = Hex.printhex2Buf(data, data.length);
        System.out.println(msg);
    }
}
